package com.yhzl.two.shop.service.impl;

import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yhzl.two.shop.common.OrderState;
import com.yhzl.two.shop.common.ServerResponse;
import com.yhzl.two.shop.common.ServiceCommonMethod;
import com.yhzl.two.shop.dto.ShopCartDto;
import com.yhzl.two.shop.entity.*;
import com.yhzl.two.shop.mapper.AddressMapper;
import com.yhzl.two.shop.mapper.OrderMapper;
import com.yhzl.two.shop.mapper.ShopCartMapper;
import com.yhzl.two.shop.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yhzl.two.shop.vo.ShopCartVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author chsm
 * @since 2018-09-04
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    private static final String SHOP_CART_DTO = "ShopCartDto";
    private static final String CHECK_STOCK = "checkStock";
    private final IProductService productService;
    private final AddressMapper addressMapper;
    private final IOrderItemService orderItemService;
    private final ShopCartMapper shopCartMapper;
    private final AliService aliService;

    @Autowired
    public OrderServiceImpl(IProductService productService, AddressMapper addressMapper, IOrderItemService orderItemService, ShopCartMapper shopCartMapper, AliService aliService) {
        this.productService = productService;
        this.addressMapper = addressMapper;
        this.orderItemService = orderItemService;
        this.shopCartMapper = shopCartMapper;
        this.aliService = aliService;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServerResponse<Map<String, Boolean>> createOrder(ShopCartVo shopCartVo, Integer uid) {
        List<ShopCart> shopCarts = shopCartMapper.selectBatchIds(shopCartVo.getSid());
        // 获取下单商品
        List<Integer> pidList = shopCarts.stream()
                .map(ShopCart::getPid)
                .collect(Collectors.toList());
        List<Product> products = (List<Product>) productService.listByIds(pidList);
        Map<String, Object> map = generateShopCartDtoAndCheckStock(shopCarts, products);
        // 生成购物车DTO对象
        List<ShopCartDto> shopCartDtos = (List<ShopCartDto>) map.get(SHOP_CART_DTO);
        // 获取校验库存信息
        Map<String, Boolean> checkErrorStock = (Map<String, Boolean>) map.get(CHECK_STOCK);
        if (checkErrorStock.size() == shopCarts.size()) {
            return ServerResponse.createErrorMessage("购物车商品库存不足，请重新下单");
        }
        // 计算合法购物车总金额
        BigDecimal sumPrice = BigDecimal.valueOf(0);
        for (ShopCartDto shopCartDto : shopCartDtos) {
            Product product = shopCartDto.getProduct();
            sumPrice = sumPrice.add(product.getPrice().multiply(BigDecimal.valueOf(shopCartDto.getNum())));
        }
        // 获取地址信息
        Address address = addressMapper.selectById(shopCartVo.getAddressId());
        // 拼接真实地址
        String addressStr = getAddress(address);
        Order order = new Order();
        // 生成纳秒级订单id
        String oid = String.valueOf(System.nanoTime());
        // 设置订单默认属性
        order.setAddress(addressStr).setOid(oid)
                .setState(OrderState.PLANCE_AN_ORDER.getCode())
                .setName(address.getName())
                .setTel(address.getTel())
                .setSumPrice(sumPrice)
                .setUid(uid);
        // 生成订单
        int count = baseMapper.insert(order);
        List<OrderItem> orderItems = generateOrderItem(shopCartDtos, oid);
        orderItemService.saveBatch(orderItems);
        // 更新商品库存和购物车信息
        updateStockAndShopCart(shopCartDtos, uid);
        if (checkErrorStock.size() == 0) {
            return ServerResponse.createSuccessMessage("下单成功");
        }
        return ServerResponse.createWarnData("部分商品由于库存不足下单失败", checkErrorStock);
    }

    @Override
    public ServerResponse<List<Order>> getOrderByUid(Integer uid) {
        List<Order> orders = baseMapper.queryByUid(uid);
        return ServerResponse.createSuccessData("获取订单信息成功", orders);
    }

    @Override
    public ServerResponse<String> updateState(Integer id, Integer state) {
        Order order = baseMapper.selectById(id);
        // 退款响应
        AlipayTradeRefundResponse alipayTradeRefundResponse = null;
        // 判断退款请求
        if (state.equals(OrderState.REFUNDED.getCode())) {
            alipayTradeRefundResponse = aliService.alipayTradeRefundService(order.getOid());
        }
        // 对退款状态进行判断
        if (alipayTradeRefundResponse != null) {
        // 退款失败提示前端用户
            if (!(alipayTradeRefundResponse.isSuccess() && "10000".equals(alipayTradeRefundResponse.getCode()))) {
                return ServerResponse.createErrorMessage("订单退款失败，请稍后重试");
            }
        }
        int count = baseMapper.updateById(new Order().setId(id).setState(state));
        return ServiceCommonMethod.returnInsert(count, "更新订单状态成功", "更新订单状态失败");
    }

    /**
     * 获取真实地址
     * 真实地址必须持久化到数据库，不得使用外键关联，
     * 否则当地址删除时会导致数据丢失
     *
     * @param address 地址信息
     * @return 真实地址字符串
     */
    private String getAddress(Address address) {
        return address.getProvince() +
                address.getCity() +
                address.getCounty() +
                address.getDetailed();
    }

    /**
     * 生成订单明细
     *
     * @param shopCartDtos 购物车DTO对象
     * @return 订单明细列表
     */
    private List<OrderItem> generateOrderItem(List<ShopCartDto> shopCartDtos, String oid) {
        return shopCartDtos.stream()
                .map(v -> new OrderItem()
                        .setName(v.getProduct().getPdesc())
                        .setImg(v.getProduct().getImg())
                        .setPrice(v.getProduct().getPrice())
                        .setNum(v.getNum())
                        .setOid(oid))
                .collect(Collectors.toList());
    }

    /**
     * 生成购物车DTO对象并校验库存
     *
     * @param shopCarts 购物车信息
     * @param products  商品信息
     * @return 购物车DTO集合与库存信息
     */
    private Map<String, Object> generateShopCartDtoAndCheckStock(List<ShopCart> shopCarts, List<Product> products) {
        Map<String, Object> map = new HashMap<>(2);
        List<ShopCartDto> shopCartDtos = new ArrayList<>(shopCarts.size());
        Map<String, Boolean> checkErrorStock = new HashMap<>(shopCarts.size());
        for (int i = 0; i < shopCarts.size(); i++) {
            Integer num = shopCarts.get(i).getNum();
            Product product = products.get(i);
            // 校验库存
            if (num <= product.getStock()) {
                shopCartDtos.add(new ShopCartDto()
                        .setNum(num)
                        .setProduct(product));
            } else {
                checkErrorStock.put(product.getName(), false);
            }
        }
        map.put(SHOP_CART_DTO, shopCartDtos);
        map.put(CHECK_STOCK, checkErrorStock);
        return map;
    }

    /**
     * 更新商品库存和购物车信息
     *
     * @param shopCartDtos 购物车信息
     * @param uid          用户id
     */
    private void updateStockAndShopCart(List<ShopCartDto> shopCartDtos, Integer uid) {
        shopCartDtos.forEach(v -> {
            // 更新商品库存
            productService.updateById(v.getProduct().setStock(v.getProduct().getStock() - v.getNum()));
            // 更新购物车信息
            shopCartMapper.delete(new UpdateWrapper<ShopCart>()
                    .eq("uid", uid)
                    .eq("pid", v.getProduct().getId()));
        });
    }
}
